﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace SocialKit.LightRest.OAuth
{
    /// <summary>
    /// Represents the consumer of OAuth.
    /// </summary>
    public class Consumer
    {
        /// <summary>
        /// Gets or sets the consumer key.
        /// </summary>
        public string Key { get; set; }

        /// <summary>
        /// Gets or sets the consumer secret.
        /// </summary>
        public string Secret { get; set; }


        /// <summary>
        /// Gets or sets the request token URI string.
        /// </summary>
        public string RequestTokenUri { get; set; }

        /// <summary>
        /// Gets or sets the authorize URI string.
        /// </summary>
        public string AuthorizeUri { get; set; }

        /// <summary>
        /// Gets or sets the access token URI string.
        /// </summary>
        public string AccessTokenUri { get; set; }

        string callback;

        /// <summary>
        /// Gets or sets the callback URI string.
        /// </summary>
        public string Callback
        {
            get
            {
                if (callback == null)
                    callback = OAuthStrings.OutOfBandCallback;

                return callback;
            }

            set { callback = value; }
        }

        /// <summary>
        /// Represents the version of OAuth, always returns "1.0".
        /// </summary>
        public const string OAuthVersion = "1.0";

        ISignatureProvider signatureProvider;

        /// <summary>
        /// Gets or sets the signature provider used to generate signature of OAuth requests.
        /// Now comes with PlainTextSignatureProvider, HMACSHA1SignatureProvider and 
        /// RSASHA1SignatureProvider(.NET Framework only, not supports .NET Compact Framework) classes.
        /// </summary>
        public ISignatureProvider SignatureProvider
        {
            get
            {
                if (signatureProvider == null)
                    signatureProvider = new HMACSHA1SignatureProvider();

                return signatureProvider;
            }

            set { signatureProvider = value; }
        }


        /// <summary>
        /// Initialize a new instance of SocialKit.LightOAuth.Consumer class with specified values.
        /// </summary>
        /// <param name="key">The consumer key.</param>
        /// <param name="secret">The consumer secret.</param>
        /// <param name="requestTokenUri">The request token uri.</param>
        /// <param name="authorizeUri">The authorize uri.</param>
        /// <param name="accessTokenUri">The access token uri.</param>
        /// <param name="callback">The callback uri or "oob" if no need a callback, the "oob" is default value.</param>
        /// <param name="signatureProvider">The signature provider, the HMACSHA1SignatureProvider is default provider.</param>
        public Consumer(string key, string secret,
            string requestTokenUri, string authorizeUri, string accessTokenUri,
            string callback,
            ISignatureProvider signatureProvider)
        {
            this.Key = key;
            this.Secret = secret;

            this.RequestTokenUri = requestTokenUri;
            this.AuthorizeUri = authorizeUri;
            this.AccessTokenUri = accessTokenUri;

            this.Callback = callback;

            this.SignatureProvider = signatureProvider;
        }

        /// <summary>
        /// Initialize a new instance of SocialKit.LightOAuth.Consumer class
        /// </summary>
        public Consumer() { }


        /// <summary>
        /// Gets the request token from server.
        /// </summary>
        /// <param name="additionalParameters">The additional parameters normalized as URI query string(like a=1&amp;b=2).</param>
        /// <returns></returns>
        public RequestToken GetRequestToken(string additionalParameters)
        {
            return GetRequestToken(RestUtility.ParseQueryString(additionalParameters).ToArray());
        }

        /// <summary>
        /// Gets the request token from server.
        /// </summary>
        /// <param name="additionalParameters">The additional parameters defined by the service provider used to retrive a request token.</param>
        /// <returns></returns>
        public RequestToken GetRequestToken(params KeyValuePair<string, string>[] additionalParameters)
        {
            var values = additionalParameters.ToList();
            values.Add(new KeyValuePair<string, string>(OAuthStrings.OAuthCallbackKey, this.Callback));

            var request = new OAuthHttpRequestMessage("GET", this.RequestTokenUri)
                .Sign(this, null, null, values.ToArray());

            var responseText = new RestClient().Send(request).ReadContentAsString();

            var tokenValues = RestUtility.ParseQueryString(responseText)
                .ToDictionary(p => p.Key, p => p.Value);

            return new RequestToken(this, tokenValues[OAuthStrings.OAuthTokenKey], tokenValues[OAuthStrings.OAuthTokenSecretKey], tokenValues);
        }
    }
}